#ifndef _ARRAY_H_
#define _ARRAY_H_

#include "Object.h"
#include "Exception.h"

namespace MySTL
{

template < typename T >
class Array : public Object
{
private:
	Array(const Array& obj);
	Array& operator =(const Array& obj);

public:
	Array();

	virtual bool get(int n, T& value) const;
	virtual T& get(int n);
	virtual const T& get(int n) const;
	virtual bool set(int n, const T& value);
	virtual int find(const T& value) const;
	virtual T* getArray() const;

	virtual T& operator [](int n);
	virtual const T& operator [](int n) const;

	virtual int length() const = 0;

protected:
	T* m_array;
};

template < typename T >
Array<T>::Array()
{
	m_array = NULL;
}

template < typename T >
bool Array<T>::get(int n, T& value) const
{
	bool ret = (n >= 0) && (n < length());

	if (ret)
	{
		value = m_array[n];
	}

	return ret;
}

template < typename T >
T& Array<T>::get(int n)
{
	if ((n >= 0) && (n < length()))
	{
		return m_array[n];
	}
	else
	{
		THROW_EXCEPTION(IndexOutOfBoundsException, "Index out of bounds in T& Array<T>::get(int n)");
	}
}

template < typename T >
const T& Array<T>::get(int n) const
{
	return const_cast<Array<T>*>(this)->get(n);
}

template < typename T >
bool Array<T>::set(int n, const T& value)
{
	bool ret = (n >= 0) && (n < length());

	if (ret)
	{
		m_array[n] = value;
	}

	return ret;
}

template < typename T >
int Array<T>::find(const T& value) const
{
	int ret = -1;

	for (int i = 0; i < length(); ++i)
	{
		if (m_array[i] == value)
		{
			ret = i;
			break;
		}
	}

	return ret;
}

template < typename T >
T* Array<T>::getArray() const
{
	return m_array;
}

template < typename T >
T& Array<T>::operator [](int n)
{
	if ((n >= 0) && (n < length()))
	{
		return m_array[n];
	}
	else
	{
		THROW_EXCEPTION(IndexOutOfBoundsException, "Index out of bounds in T& Array<T>::operator [](int n)");
	}
}

template < typename T >
const T& Array<T>::operator [](int n) const
{
	return const_cast<Array<T>&>(*this)[n];
}

}

#endif